package edu.zqu.collegeField.framework.easyexcel.listener;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.fastjson.JSON;
import edu.zqu.collegeField.framework.easyexcel.exceldata.ErrorExcelRow;
import edu.zqu.collegeField.framework.easyexcel.exceldata.ExcelData;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Slf4j
public class ExcelListener<T> extends AnalysisEventListener<T> {
    private static final Logger logger = LoggerFactory.getLogger(ExcelListener.class);
    @Getter
    private ExcelData<T> excelData;

    private List<T> rows = new ArrayList<>();

    private List<ErrorExcelRow> errorExcelRows = new ArrayList<>();


    public ExcelListener() {
        excelData = new ExcelData<>();
    }

    /**
     * excel一行行解析
     *
     * @param entity
     * @param analysisContext
     */
    @Override
    public void invoke(T entity, AnalysisContext analysisContext) {
        Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
        Set<ConstraintViolation<T>> constraintViolations = validator.validate(entity);
        if (constraintViolations.size() > 0) {
            String message = "";
            for (ConstraintViolation<T> constraintViolation : constraintViolations) {
                message = message + "," + constraintViolation.getMessage();
            }
            ErrorExcelRow errorExcelRow = this.setAndReturnErrorExcelRow(analysisContext, message);
            errorExcelRows.add(errorExcelRow);
        } else {
            rows.add(entity);
        }
    }

    /**
     * excel数据行都解析完毕时调用
     *
     * @param analysisContext
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        excelData.setErrorRows(errorExcelRows);
        excelData.setRows(rows);
    }


    /**
     * 在转换异常 获取其他异常下会调用本接口。抛出异常则停止读取。如果这里不抛出异常则 继续读取下一行。
     */
    @Override
    public void onException(Exception exception, AnalysisContext analysisContext) {
    }

    /**
     * 这里为一行行的返回头
     *
     * @param headMap
     * @param context
     */
    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
    }

    private ErrorExcelRow setAndReturnErrorExcelRow(AnalysisContext analysisContext, String errorMsg) {
        int rowIndex = analysisContext.readRowHolder().getRowIndex();
        int sheetNo = analysisContext.readSheetHolder().getSheetNo();
        String sheetName = analysisContext.readSheetHolder().getSheetName();
        ErrorExcelRow errorExcelRow = ErrorExcelRow.builder()
                .rowNum(rowIndex).sheetName(sheetName).sheetNo(sheetNo)
                .errorMessage(errorMsg).build();
        return errorExcelRow;
    }
}
